# 看广告视频的功能已经比较完善，不需要进行分拆了，这个文件是gameplay_for_ui进行调试的备份文件。3-14
#这个是test_file_in_one的复制过来的文件
#这个文件可以正确的升级资源田和建筑
#这个文件用来和app.py来实现通过UI来操作功能
#这个是不看广告升级资源的操作
#将登录放到循环计时外面，减少登录次数
#如果你需要在其他地方打印配置信息，可以直接在主程序中调用 config_manager.print_config()，而不需要在 LoginAutoTimer 类中实现。
#优化了看视频的逻辑，通过截图来判断是否视频成功。
#加了避免程序自动打开浏览器的设置


import os
import sys
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import threading
import ast
from datetime import datetime
import re
from selenium.webdriver.common.by import By
import pyautogui
from PIL import ImageChops

class ConfigManager:
    def __init__(self, filename):
        self.filename = filename
        self.config = self.parse_config(filename)

    def parse_config(self, filename):
        config = {}
        with open(filename, 'r', encoding='utf-8') as f:
            lines = f.readlines()

        current_key = None
        list_buffer = []
        dict_buffer = []
        in_list = False
        in_dict = False

        for line in lines:
            line = line.strip()

            if not line or line.startswith('#'):  # 忽略空行和以#开头的注释行
                continue

            if '=' in line and not in_list and not in_dict:
                key, value = map(str.strip, line.split('=', 1))
                if value.startswith('['):
                    current_key = key
                    list_buffer = [value]
                    in_list = True
                    if value.endswith(']'):
                        in_list = False
                        list_str = ' '.join(list_buffer).replace('\\', '')
                        config[current_key] = ast.literal_eval(list_str)
                elif value.startswith('{'):
                    current_key = key
                    dict_buffer = [value]
                    in_dict = True
                    if value.endswith('}'):
                        in_dict = False
                        dict_str = ' '.join(dict_buffer).replace('\\', '')
                        config[current_key] = ast.literal_eval(dict_str)
                else:
                    if value.lower() in ('true', 'false'):
                        config[key] = value.lower() == 'true'
                    elif value.isdigit():
                        config[key] = int(value)
                    else:
                        # 移除注释部分
                        value = value.split('#', 1)[0].strip()
                        config[key] = value.strip('"')
            elif in_list:
                # 移除注释部分
                line = line.split('#', 1)[0].strip()
                if line:
                    list_buffer.append(line)
                if line.endswith(']'):
                    in_list = False
                    list_str = ' '.join(list_buffer).replace('\\', '')
                    config[current_key] = ast.literal_eval(list_str)
            elif in_dict:
                # 移除注释部分
                line = line.split('#', 1)[0].strip()
                if line:
                    dict_buffer.append(line)
                if line.endswith('}'):
                    in_dict = False
                    dict_str = ' '.join(dict_buffer).replace('\\', '')
                    config[current_key] = ast.literal_eval(dict_str)
        return config

    def print_config(self):
        building_name_mapping = self.get_building_name_mapping()
        print(f"每次运行后等待时间: {self.config['interval']}秒钟")
        print(f"本次操作运行次数: {self.config['max_runs']}")
        print(f"登录地址: {self.config['game_login_url']}")
        print(f"账号: {self.config['username']}")
        print(f"密码: {'*' * len(str(self.config['password']))}")
        print(f"村庄资源页数量: {len(self.config['village_urls'])}")
        print(f"建筑页面数量: {len(self.config['building_urls'])}")

        # 转换建筑ID为中文名称
        build_sequence_names = [building_name_mapping.get(build_id, build_id) for build_id in
                                self.config['build_sequence']]
        print(f"建筑种类包括: {build_sequence_names}")
        print(f"文件路径为：{self.filename}")

    def get_building_name_mapping(self):
        # 建筑ID与中文名称的映射关系
        building_name_mapping = {
            "5": "鋸木廠", "6": "磚廠", "7": "鋼鐵鑄造廠", "8": "麵粉廠",
            "9": "麵包店", "10": "倉庫", "11": "穀倉", "13": "盔甲廠",
            "14": "競技場", "15": "村莊大樓", "16": "集結點", "17": "市場",
            "18": "大使館", "19": "兵營", "20": "馬廄", "21": "工场",
            "22": "研究院", "23": "山洞", "24": "城鎮廳", "25": "行宮",
            "26": "皇宫", "27": "宝物库", "28": "交易所", "29": "大兵营",
            "30": "大马厩", "31": "城牆", "36": "陷阱机", "37": "英雄宅",
            "38": "大仓库", "39": "大谷仓", "41": "放牧水槽", "46": "醫院"
        }
        return building_name_mapping

def get_config_path():
    # 获取当前执行文件的路径
    current_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    # 构造config.txt文件的路径
    config_path = os.path.join(current_dir, "config.txt")
    return config_path

class LoginAutoTimer(threading.Thread):
    def __init__(self, driver, village_urls, building_urls, build_sequence, interval, max_runs):
        super().__init__()
        self.driver = driver
        self.village_urls = village_urls
        self.building_urls = building_urls
        self.build_sequence = build_sequence
        self.interval = interval
        self.max_runs = max_runs
        self.run_count = 0
        self.stop = False

    def run(self):
        config_manager = ConfigManager(get_config_path())
        building_name_mapping = config_manager.get_building_name_mapping()

        while not self.stop and self.run_count < self.max_runs:
            page_operator = PageOperator(self.driver, self.village_urls)
            page_operator.check_and_upgrade_resources()
            new_building_operator = NewBuildingOperator(self.driver, self.building_urls, self.build_sequence)
            new_building_operator.check_and_upgrade_buildings()
            self.run_count += 1
            print(f"{self.run_count} ：已运行 {self.run_count} 次，等待 {self.interval} 秒后继续...")
            now = datetime.now()
            formatted_time = now.strftime("%Y-%m-%d %H:%M:%S")
            print("当前系统时间:", formatted_time)

            for i in range(self.interval, 0, -10):
                print(f"{i}", end=" ")
                time.sleep(10) #屏幕每次输出时间间隔
            print("")
        print(f"程序已运行 {self.max_runs} 次，自动停止。")

class LoginManager:
    def __init__(self, game_login_url, username, password):
        self.game_login_url = game_login_url
        self.username = username
        self.password = password

    def login(self):
        options = Options()
        # 禁用扩展和弹出窗口，避免干扰
        options.add_argument("--disable-extensions")
        options.add_argument("--disable-popup-blocking")
        options.add_argument("--disable-notifications")
        options.add_argument("--no-default-browser-check")
        options.add_argument("--no-first-run")
        options.add_argument("--disable-gpu")
        # 设置浏览器为无头模式（后台运行）
        # options.add_argument("--headless")
        driver = webdriver.Chrome(options=options)
        driver.set_window_size(1200, 768)
        try:
            driver.get(self.game_login_url)
            time.sleep(5)
            username_field = driver.find_element(By.NAME, "name")
            username_field.send_keys(self.username)
            time.sleep(1)

            password_field = driver.find_element(By.NAME, "password")
            password_field.send_keys(self.password)
            time.sleep(1)

            login_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
            login_button.click()
            time.sleep(3)

            login_url = driver.current_url
            print("登录成功")
            print("当前登录URL：", login_url)

            return driver

        except Exception as e:
            print("登录失败，错误信息：", e)
            driver.quit()  # 确保在登录失败时关闭浏览器实例
            return None

class PageOperator:
    def __init__(self, driver, village_urls, save_picture=True):
        self.driver = driver
        self.village_urls = village_urls
        self.save_picture = save_picture  # 是否保存截图的开关
        self.upgrade_handler = UpgradeHandler(driver, save_picture)

    def check_and_upgrade_resources(self):
        try:
            for village_url in self.village_urls:
                print(f":-->正在访问村庄资源页面: {village_url}")  # 保留原始打印输出
                self.driver.get(village_url)
                time.sleep(3)
                while True:
                    upgrade_candidates = self._get_upgrade_candidates()
                    if not upgrade_candidates:
                        print(":----当前村庄没有可升级的资源，继续下一个村庄")  # 保留原始打印输出
                        break
                    upgrade_candidates.sort(key=lambda x: x[1])
                    resource_id, level = upgrade_candidates[0]
                    print(f":--准备升级第 {resource_id}号资源位置，当前等级={level}")  # 保留原始打印输出
                    self._upgrade_resource(resource_id, village_url)
        except Exception as e:
            print(f"在资源页面操作时发生错误: {e}")

    def _get_upgrade_candidates(self):
        upgrade_candidates = []
        try:
            # 定位到 resourceFieldContainer 元素
            container = self.driver.find_element(By.ID, "resourceFieldContainer")
            # 查找所有符合条件的<a>标签
            elements = container.find_elements(By.XPATH,
                                               ".//a[contains(@class, 'good') and not(contains(@class, 'maxLevel')) and not(contains(@class, 'notNow'))]")
            for element in elements:
                try:
                    # 获取 data-gid 属性作为 resource_id
                    resource_id = element.get_attribute("data-aid")
                    if not resource_id:
                        continue
                    resource_id = int(resource_id)
                    # 获取 level 信息
                    level_match = re.search(r'level(\d+)', element.get_attribute("class"))
                    if level_match:
                        level = int(level_match.group(1))
                        upgrade_candidates.append((resource_id, level))
                except Exception as e:
                    print(f"在处理资源元素时发生错误: {e}")
                    continue
        except Exception as e:
            print(f"在查找资源容器时发生错误: {e}")
        return upgrade_candidates

    def _upgrade_resource(self, resource_id, village_url):
        try:
            url = f"https://ts1.x1.asia.travian.com/build.php?id={resource_id}"
            print(f":----正在访问第 {resource_id}号资源位置 的升级页面: {url}")  # 保留原始打印输出
            self.upgrade_handler.handle_upgrade_with_video(url, village_url)
        except Exception as e:
            print(f"升级资源时发生错误: {e}")

class NewBuildingOperator:
    def __init__(self, driver, building_urls, build_sequence, save_picture=True):
        self.driver = driver
        self.building_urls = building_urls
        self.build_sequence = build_sequence
        self.save_picture = save_picture  # 是否保存截图的开关
        self.upgrade_handler = UpgradeHandler(driver, save_picture)

    def check_and_upgrade_buildings(self):
        try:
            for village_url in self.building_urls:
                self.driver.get(village_url)
                print(f":-->正在访问村庄建筑页面:：{village_url}")
                time.sleep(3)
                self._build_structures_in_village()
        except Exception as e:
            print(f"在建筑页面操作时发生错误：{e}")

    def _build_structures_in_village(self):
        try:
            building_buttons = self.driver.find_elements(By.XPATH, "//a[contains(@class, 'good') and contains(@class, 'colorLayer') and contains(@class, 'level')]")
            valid_buttons = []
            for button in building_buttons:
                try:
                    href = button.get_attribute("href")
                    gid_match = re.search(r"gid=(\d+)", href)
                    data_level = button.get_attribute("data-level")
                    if gid_match and data_level and gid_match.group(1) in self.build_sequence:
                        valid_buttons.append((button, int(data_level)))
                except Exception as e:
                    print(f"解析建筑按钮时发生错误：{e}")

            if valid_buttons:
                valid_buttons.sort(key=lambda x: x[1])
                target_button = valid_buttons[0][0]
                target_href = target_button.get_attribute("href")
                print(f"----正在访问建筑升级页面: {target_href}")  # 保留原始打印输出
                self.upgrade_handler.handle_upgrade_with_video(target_href, self.building_urls[0])
                # 这里假设返回到建筑列表的第一个村庄页面，可以根据实际需求调整
                # self.driver.back()
                # time.sleep(1)
            else:
                print(":----当前页面没有可升级的建筑")  # 保留原始打印输出
        except Exception as e:
            print(f"在建筑序列操作时发生错误：{e}")

class UpgradeHandler:
    def __init__(self, driver, save_picture=True):
        self.driver = driver
        self.save_picture = save_picture  # 是否保存截图的开关

    def handle_upgrade_with_video(self, upgrade_url, return_url):
        try:
            print(f":----正在访问升级页面: {upgrade_url}")  # 保留原始打印输出
            self.driver.get(upgrade_url)
            time.sleep(1)

            # 尝试点击视频加速按钮
            try:
                video_button = self.driver.find_element(By.CSS_SELECTOR, "button.textButtonV1.green.build.videoFeatureButton")
                if video_button:
                    video_button.click()
                    print(":------已选择视频广告加速按钮")  # 保留原始打印输出
                    time.sleep(7)
                    pyautogui.click(750, 630)
                    time.sleep(5)
                    print(":--------5秒前已点击视频播放按钮位置准备播放视频")  # 保留原始打印输出

                    # 检测视频是否成功播放
                    video_played = self._check_video_played_by_screenshot()
                    if video_played:
                        print(":----------------视频播放成功")  # 保留原始打印输出
                        time.sleep(45)  # 等待视频播放完成
                    else:
                        print("视频播放失败，返回资源升级页面并切换到普通升级按钮")  # 保留原始打印输出
                        # 返回到资源升级页面
                        self.driver.get(upgrade_url)
                        time.sleep(3)
                        # 尝试点击普通升级按钮
                        try:
                            resource_button = self.driver.find_element(By.CSS_SELECTOR, "button.textButtonV1.green.build")
                            if resource_button:
                                resource_button.click()
                                print("已点击普通升级按钮")  # 保留原始打印输出
                                time.sleep(2)
                        except Exception as e:
                            print(f"点击普通升级按钮时发生错误: {e}")
            except Exception as e:
                #print(f"点击视频加速按钮时发生错误: {e}")
                print(f"点击视频加速按钮时发生错误:") #这里其实是0级资源田没有看广告按钮，找不到广告按钮报错
                # 如果视频加速按钮不存在或点击失败，返回到资源升级页面并尝试点击普通升级按钮
                self.driver.get(upgrade_url)
                time.sleep(1)
                try:
                    resource_button = self.driver.find_element(By.CSS_SELECTOR, "button.textButtonV1.green.build")
                    if resource_button:
                        resource_button.click()
                        print("已点击普通升级按钮")  # 保留原始打印输出
                        time.sleep(2)
                except Exception as e:
                    print(f"点击普通升级按钮时发生错误: {e}")

            # 返回到指定页面
            print(f":--返回到页面: {return_url}")  # 保留原始打印输出
            self.driver.get(return_url)
            time.sleep(1)

        except Exception as e:
            print(f"升级操作时发生错误: {e}")

    def _check_video_played_by_screenshot(self):
        try:
            # 定义截图区域（根据实际情况调整坐标和大小）
            x, y, width, height = 600, 300, 500, 400

            # 第一次截图
            print(":----------第一次截图")  # 保留原始打印输出
            screenshot1 = pyautogui.screenshot(region=(x, y, width, height))
            if self.save_picture:
                screenshot1.save("screenshot1.png")  # 保存第一次截图

            time.sleep(5)  # 等待5秒

            # 第二次截图
            print(":------------第二次截图")  # 保留原始打印输出
            screenshot2 = pyautogui.screenshot(region=(x, y, width, height))
            if self.save_picture:
                screenshot2.save("screenshot2.png")  # 保存第二次截图

            # 比较两次截图的差异
            diff = ImageChops.difference(screenshot1, screenshot2)
            if diff.getbbox():
                print(":--------------两次截图不同，视频播放成功")  # 保留原始打印输出
                return True
            else:
                print(":-------------两次截图相同，视频播放失败")  # 保留原始打印输出
                return False

        except Exception as e:
            print(f"截图比对时发生错误: {e}")
            return False

if __name__ == "__main__":
    config_path = get_config_path()
    config_manager = ConfigManager(config_path)
    config_manager.print_config()

    # 这里可以继续使用 config_manager.config 获取配置参数
    # 例如：
    interval = config_manager.config['interval']
    max_runs = config_manager.config['max_runs']
    game_login_url = config_manager.config['game_login_url']
    username = config_manager.config['username']
    password = config_manager.config['password']
    village_urls = config_manager.config['village_urls']
    building_urls = config_manager.config['building_urls']
    build_sequence = config_manager.config['build_sequence']

    # 登录网站
    login_manager = LoginManager(game_login_url, username, password)
    driver = login_manager.login()
    if driver:
        # 启动计时器，传入登录后的 driver
        timer = LoginAutoTimer(driver, village_urls, building_urls, build_sequence, interval, max_runs)
        timer.start()
        timer.join()  # 等待计时器线程完成

        # 关闭浏览器
        driver.quit()
        print("程序执行完成，浏览器已关闭。")
    else:
        print("登录失败，程序无法继续执行。")